/**
 * ajax 模块，完成对服务器的请求及异常处理
 * 
 * @returns
 */
(function()
{
	var ajaxFun = function()
	{
		this._serverName = ''; // 当前服务 // UI归属的服务名称
		this._serverName0 = '';
		// 最后一个等待执行的任务
		this._nextLastRun = 0;
		// 缓存数据
		this._cache = {};
		// 缓存时间，1小时
		this._cacheTime = 3600;
		this._para = {};
	};
	/**
	 * 设置当前请求参数
	 */
	ajaxFun.prototype.setMethod = function(method)
	{
		this._para['method'] = method;
	}
	ajaxFun.prototype.setPara = function(para)
	{
		this._para['para'] = para;
	}
	ajaxFun.prototype.setBackfun = function(backfun)
	{
		this._para['backfun'] = backfun;
	}
	ajaxFun.prototype.setFailedfun = function(failedfun)
	{
		this._para['failedfun'] = failedfun;
	}
	ajaxFun.prototype.setNotNeedLogin = function(notNeedLogin)
	{
		this._para['notNeedLogin'] = notNeedLogin;
	}
	ajaxFun.prototype.setBackRequest = function(backRequest)
	{
		this._para['backRequest'] = backRequest;
	}
	/**
	 * 设置超时时间，单位为m，存储为ms
	 */
	ajaxFun.prototype.setTimeout = function(timeout)
	{
		if (timeout > 0 && timeout < 1000)
			timeout = timeout * 1000;
		this._para['timeout'] = timeout;
	}
	ajaxFun.prototype.setRunCaption = function(runCaption)
	{
		this._para['runCaption'] = runCaption;
	}
	ajaxFun.prototype.setCacheMark = function(cacheMark)
	{
		this._para['cacheMark'] = cacheMark;
	}
	ajaxFun.prototype.setRunningFun = function(runningFun)
	{
		this._para['runningFun'] = runningFun;
	}
	ajaxFun.prototype.setCompleteFun = function(completeFun)
	{
		this._para['completeFun'] = completeFun;
	}
	ajaxFun.prototype.setUrl = function(url)
	{
		this._para['thisUrl'] = url;
	}
	/**
	 * 发起请求，如果参数出错则返回假，成功进行了实际的请求（不含缓存）返回真，其它则不返回数据
	 */
	ajaxFun.prototype.request = function(method, para, backfun, failedfun, notNeedLogin, backRequest, timeout, runCaption, cacheMark, runningFun, thisUrl, mustLoginWhenNeed)
	{
		if (!window.login)
			return;
		var that = this;
		if (app.lockScreen())
		{
			app.lockScreen(0, function()
			{
				that.request(method, para, backfun, failedfun, notNeedLogin, backRequest, timeout, runCaption, cacheMark, runningFun, thisUrl, mustLoginWhenNeed)
			});
			return;
		}
		// ////////////////////////
		// 赋予本次参数值 ，只一次
		if (timeout > 0 && timeout < 1000)
			timeout = timeout * 1000;
		method = method || this._para['method'];
		para = para || this._para['para'];
		backfun = backfun || this._para['backfun'];
		failedfun = failedfun || this._para['failedfun'];
		notNeedLogin = notNeedLogin || this._para['notNeedLogin'] || app.isSinglePage();
		backRequest = backRequest || this._para['backRequest'];
		timeout = timeout || this._para['timeout'];
		runCaption = runCaption || this._para['runCaption'];
		cacheMark = cacheMark || this._para['cacheMark'];
		runningFun = runningFun || this._para['runningFun'];
		thisUrl = thisUrl || (this._para['thisUrl'] || '');
		var completeFun = this._para['completeFun'] || null;
		var grantAuthIdAndMd5 = this._para['grantAuthIdAndMd5'] || '';
		this._para = {};
		// ///////////////////////////////////////////////////
		// 检验参数及可行性
		// 首先序列化参数
		if (para && typeof para != 'string')
		{
			for ( var i in para)
			{
				if (para[i] == undefined)
					delete para[i];
			}
			var paraStr = JSON.stringify(para);
		}
		else
			var paraStr = para;
		// 根据方法获取相应的网址
		var url = this.getUrl(method, thisUrl);
		if (!url)
		{
			if (app.getBusinessId() > 0)
				layer.msg('not find url according to method : ' + method);
			return false;
		}
		// /////////////////////////////////////////
		// 尝试读取缓存
		if (cacheMark)
		{
			cacheMark = (cacheMark + ' ').trim();
			if (cacheMark.indexOf(method) !== 0)
				cacheMark = method + '_' + cacheMark;
			if (this._cache[cacheMark])
			{
				var time = this._cache[cacheMark].time;
				if (time >= getTime() - this._cacheTime)
				{
					if (backfun)
					{
						var response = JSON.parse(this._cache[cacheMark].responseStr);
						backfun(response.data, response.adata, app.fw(response.msg), response.code);
					}
					return;
				}
				else if (time < 0)
				{
					// 正在执行，稍微等会再试
					setTimeout(function()
					{
						that.request(method, paraStr, backfun, failedfun, notNeedLogin, backRequest, timeout, runCaption, cacheMark, runningFun, thisUrl, mustLoginWhenNeed);
					}, 333);
					return;
				}
			}
			else
			{
				this._cache[cacheMark] = {
					time : -1
				};
			}
		}
		// ////////////////////////////////////////////////
		// 需要排队执行 , 正在等待，或刚刚正在读取缓存
		var nowMs = new Date().getTime();
		if (!backRequest && (this._waiting() || this._nextLastRun > nowMs))
		{
			var dm = 333;
			if (this._nextLastRun > nowMs)
				dm = this._nextLastRun - nowMs + dm;
			this._nextLastRun = nowMs + dm;
			setTimeout(function()
			{
				that.request(method, paraStr, backfun, failedfun, notNeedLogin, backRequest, timeout, runCaption, cacheMark, runningFun, thisUrl, mustLoginWhenNeed);
			}, dm);
			return;
		}
		// 取得token，如果未登录，token为空
		var token = login.isLogin() ? app.getStorage('token') : '';
		// ////////////////////////////////////////
		// 针对具体微服务的请求
		if (method.indexOf('wtp.login.') !== 0)
		{
			// 登陆界面不允许访问
			if (!backRequest && this._isShowFace())
			{
				if (config.debug)
					errorMsg('inner error(95642574) : ' + method);
				return false;
			}
			// 必须有商家
			if (app.getBusinessId() <= 0 && token && !app.isSinglePage())
			{
				app.selectBusiness(function(id)
				{
					if (id > 0)
					{
						that.request(method, paraStr, backfun, failedfun, notNeedLogin, backRequest, timeout, runCaption, cacheMark, runningFun, thisUrl, mustLoginWhenNeed);
					}
				});
				return;
			}
		}
		// //////////////////////////////////////////
		// 登录验证，如果没有登录就立即登录
		if (!backRequest)
		{
			if (!notNeedLogin && !token)
			{
				app.doLogin(function()
				{
					that.request(method, paraStr, backfun, failedfun, true, false, timeout, runCaption, cacheMark, runningFun, thisUrl, mustLoginWhenNeed);
				}, true);
				return;
			}
		}
		else
		{
			if (!notNeedLogin && !token)
			{
				// 后台运行需要登陆而没有登录的，直接忽略
				return false;
			}
		}
		// /////////////////////////////////////////////
		// 添加调试代码
		if (config.debug && config.xdebug)
		{
			url = this._addToUrl(url, config.xdebug);
		}
		// //////////////////////////
		// 组织请求参数
		var postData = {
			para : paraStr,
			method : method,
			token : token ? token : config.defaultToken,
		}
		if (grantAuthIdAndMd5)
			postData['grantAuthId'] = grantAuthIdAndMd5;
		// ////////////////////////////////////////
		// 获取超时时间
		if (!(timeout > 0))
		{
			timeout = config.ajaxTimeout > 0 ? config.ajaxTimeout : 5000;
		}
		// //////////////////////////////////////////////////
		// 记录当前状态
		if (!backRequest)
		{
			this.runCaption = runCaption ? runCaption : method;
			this._waiting(333, nowMs, timeout, false, method);
			if (config.debug && timeout != config.ajaxTimeout && (timeout - Math.floor(timeout) < 0.01))
				postData['timeout'] = timeout;
		}
		// //////////////////////////////////////////////////
		// 登录功能
		var justLoginByWxid = false;
		var isLoginAction = (method == 'wtp.login.user.login');
		if (isLoginAction)
		{
			var driverKey = app.driverKey();
			if (driverKey)
				postData['driverKey'] = driverKey;
			var pa = JSON.parse(postData.para);
			if (pa['wxid'])
			{
				justLoginByWxid = true;
				login.isLoginByWxid(true, pa['wxid']);
			}
			else if (app.getStorage('tryWxId'))
			{
				pa['oldwxid'] = app.getStorage('tryWxId', false, 1200 * 1000);
				postData.para = JSON.stringify(pa);
			}
		}
		if (!backRequest && (!notNeedLogin || isLoginAction) && !app.isSinglePage()) // 传入互斥终端标示
		{
			var terminal = this.getTerminal(isLoginAction);
			if (terminal)
				postData['terminal'] = terminal;
		}
		if (runningFun)
			runningFun(true);
		$.ajax({
			url : url,
			type : "POST",
			timeout : timeout,
			data : postData,
			cache : false,
			success : function(response)
			{
				if (runningFun)
					runningFun(false);
				if (!backRequest)
					that._waiting(-1);
				if (typeof response == 'string')
				{
					if (!backRequest)
					{
						if (response == '')
						{
							that._setTopRunningStatus(false, true, app.w('login.msg.noResponse'));
						}
						else
							showMsg(response);
					}
					return;
				}
				else if (response.data === undefined && response.adata === undefined && !response.token)
				{
					if (backfun)
						backfun([], {}, '', 0);
					return;
				}
				// 正常信息，刷新token
				if (response.token && response.code <= 0 && !backRequest)
				{
					// 只有这个方法可以解除登出的禁锢
					if (isLoginAction && !justLoginByWxid)
					{
						login.clearLogOut();
					}
					login.isLogin(response.token);
				}
				response.token = '';
				if (!response.msg)
					response.msg = '';
				// 保存缓存
				if (cacheMark && response.code <= 0)
				{
					that._cache[cacheMark] = {
						time : getTime(),
						responseStr : JSON.stringify(response),
					};
				}
				// 有信息或错误
				if (response.code != 0)
				{
					// 未登录，或登录过时
					if (response.code == that.getErrorCode('ER_NOT_LOGIN'))
					{
						if (failedfun)
							failedfun('<p>(' + method + ')' + app.fw(response.msg), app.fw(response.msg), response.code, response);
						else
						{
							if (!backRequest)
							{
								if (notNeedLogin)
									that._showMsg(postData, response);
								else
								{
									if (left.showWrapper())
									{
										login.logOut(function()
										{
											app.doLogin(function()
											{
												mustLoginWhenNeed = true;
												that.request(method, paraStr, backfun, failedfun, true, false, timeout, runCaption, cacheMark, runningFun, thisUrl, mustLoginWhenNeed);
											}, !mustLoginWhenNeed);
										}, true);
									}
									else
									{
										login.logOut(null, true, true);
									}
								}
							}
						}
						return;
					}
					// 被踢出
					else if (response.code == that.getErrorCode('ER_LOGIN_BY_OTHER'))
					{
						if (app.isSinglePage())
						{
							layer.msg('login by other');
							if (failedfun)
								failedfun(app.fw(response.msg), app.fw(response.msg), response.code, response);
						}
						else
						{
							if (that.loginByOtherIndex)
								layer.close(that.loginByOtherIndex);
							that.loginByOtherIndex = errorMsg(app.w('login.msg.loginByOther'), '', function()
							{
								if (failedfun)
									failedfun(app.fw(response.msg), app.fw(response.msg), response.code, response);
								// 重新登陆
								login.logOut(function()
								{
									if (!left.showWrapper())
										app.setHome();
									else
									{
										app.doLogin(function()
										{
											mustLoginWhenNeed = true;
											that.request(method, paraStr, backfun, failedfun, true, false, timeout, runCaption, cacheMark, runningFun, thisUrl, mustLoginWhenNeed);
										}, false);
									}
								}, true);
							});
						}
						return;
					}
					else if (response.code == that.getErrorCode('ER_SERVER_ERROR'))
					{
						if (response.debugmessage)
						{
							if (!backRequest || config.debug)
								showHtml(arrToShowStr(response), true);
							else
								that._setTopRunningStatus(false, true, 'BACK REQUEST : <br>SERVER ERROR');
							return;
						}
					}
					else if (response.code == that.getErrorCode('ER_UNAUTHORIZED') && !backRequest)
					{
						// 需要授权
						var haveNeedAuths = that._haveNeedAuths(response);
						if (haveNeedAuths && method.indexOf('wtp.login.tools.grant.') < 0)
						{
							var msg = response.msg;
							msg = msg.replace(/\(.*?\)/g, '');
							msg = msg.replace(/<p>[\s\r\n]{0,32}\:/g, '<p>');
							msg = msg.replace(/<p>[\s\r\n]{0,32}<\/p>/g, '');
							msg = msg.replace(/<p>[\s\r\n]{0,32}<p>/g, '<p>');
							var md51 = md5(paraStr);
							var auth = response.adata.needAuths;
							var bid = response.adata.needAuthsBusinessId;
							confirm(app.fw(msg) + that._getAuthStrFromnAuths(auth) + '<p>&nbsp;<p>' + app.w('login.msg.grantAuthMsg2'), function()
							{
								that._grantAuth('<p>method : ' + method, md51, auth, bid, function(grantAuthId, md52)
								{
									if (grantAuthId)
									{
										if (md51 != md52)
										{
											errorMsg('md5Sign error');
											return;
										}
										grantAuthId += ':' + md52;
									}
									else
										grantAuthId = '';
									that._para['grantAuthIdAndMd5'] = grantAuthId;
									that.request(method, paraStr, backfun, failedfun, true, false, timeout, runCaption, cacheMark, runningFun, thisUrl, mustLoginWhenNeed);
								}, 0, null, method);
							});
							return;
						}
					}
					// 正常信息
					if (response.code < 0)
					{
						if (backfun)
						{
							var msg = response.msg.replace(/\(wtp\.[^\)]*\)/g, '');
							backfun(response.data, response.adata, msg, response.code);
						}
						else if (!backRequest)
							that._showMsg(postData, response);
					}
					else
					{
						if (that._isShowFace())
							layer.msg(app.fw(response.msg));
						else if (!backRequest)
						{
							if (!failedfun)
								that._showMsg(postData, response);
						}
						if (failedfun)
							failedfun('<p>WTP : (' + method + ')' + app.fw(response.msg), app.fw(response.msg), response.code, response);
					}
				}
				else if (backfun)
				{
					backfun(response.data, response.adata, app.fw(response.msg), response.code);
				}
			},
			error : function(XMLHttpRequest, textStatus)
			{
				if (runningFun)
					runningFun(false);
				if (!backRequest)
					that._waiting(-1);
				if ('timeout' == textStatus)
				{
					var responseText = method + ':<br>' + app.w('requestTimeout');
				}
				else if (!XMLHttpRequest.responseText)
				{
					var responseText = app.w('login.msg.NoResponse');
					textStatus = 'noresponse';
				}
				else
				{
					var responseText = XMLHttpRequest.responseText;
					if (!textStatus)
						textStatus = 'error';
				}
				if (!backRequest)
				{
					if (responseText.length >= 2048)
					{
						showHtml(responseText);
					}
					else if ('noresponse' == textStatus || 'timeout' == textStatus)
					{
						var reTry = false;
						confirm(app.w('login.msg.noResponseAndRetry'), function()
						{
							if ('timeout' == textStatus)
							{
								timeout = Math.round(timeout * 4) + 5;
								timeout = timeout < 25 || !timeout ? 25 : timeout;
							}
							textStatus = '';
							that.request(method, paraStr, backfun, failedfun, notNeedLogin, backRequest, timeout, runCaption, cacheMark, runningFun, thisUrl, mustLoginWhenNeed);
							reTry = true;
							return;
						}, null, false, false, function()
						{
							if (failedfun && !reTry)
							{
								msg = app.w('requestTimeout');
								failedfun('<p>(' + method + ')' + msg, msg, '', {});
							}
							if ('timeout' == textStatus)
							{
								that._setTopRunningStatus(false, true, app.w('requestTimeout'));
							}
						}, app.w('reTry'));
					}
				}
				else if (failedfun)
				{
					if (textStatus == 'timeout')
					{
						responseText = textStatus = app.w('requestTimeout');
					}
					else if (textStatus == 'noresponse')
					{
						responseText = textStatus = app.w('login.msg.NoResponse');
					}
					else if (!responseText)
						responseText = '';
					failedfun(responseText.substring(0, 256), textStatus, -1, {});
				}
			},
			complete : function()
			{
				if (cacheMark && that._cache[cacheMark] && that._cache[cacheMark].time < 0)
				{
					that._cache[cacheMark].time = 0;
				}
				if (completeFun)
					completeFun();
				if (justLoginByWxid)
					login.isLoginByWxid(false);
			}
		});
		return true;
	}
	/**
	 * 清除缓存
	 */
	ajaxFun.prototype.clearCacheMark = function(method, cacheMark)
	{
		if (cacheMark)
		{
			cacheMark = (cacheMark + ' ').trim();
			if (cacheMark.indexOf(method) !== 0)
				cacheMark = method + '_' + cacheMark;
			if (this._cache[cacheMark])
			{
				this._cache[cacheMark] = undefined;
			}
		}
	}
	/**
	 * 取得客户端指纹 除非是登录行为，否则每3分钟登录一次
	 */
	ajaxFun.prototype.getTerminal = function(isLoginAction, mustGet)
	{
		if (!window.app)
			return '';
		if (this.getTerminal.mark && !isLoginAction)
			return this.getTerminal.mark;
		var k00 = '0000000000000000000000';
		var storagekey = 'terminal_mark_1.0';
		var mark2 = app.getStorage(storagekey);
		var t = parseInt(mark2.substring(0, 10));
		// 一个终端号保存7天
		if (mark2.length != 16 || (t < getTime() - 3600 * 24 * 7 && isLoginAction))
		{
			if (isLoginAction)
			{
				mark2 = ((new Date().getTime()) + '' + Math.floor(Math.random() * 999999999) + k00).substring(0, 16);
				app.setStorage(storagekey, mark2);
			}
			else
				return '';
		}
		var mark1 = 'pc';
		if (app.vm)
		{
			var ua = navigator.userAgent.toLowerCase();
			if (ua.indexOf('miniprogram') >= 0)
				mark1 = 'mi';
			else if (ua.indexOf('micromessenger') >= 0)
				mark1 = 'wx';
			else
				mark1 = 'mo';
		}
		var mark0 = config.terminalName || window.location.host.split('.')[0];
		this.getTerminal.mark = mark1 + '-' + mark0 + '.' + mark2;
		return this.getTerminal.mark + (isLoginAction ? '.login' : '');
	}
	/**
	 * 设置当前微服务
	 */
	ajaxFun.prototype.setServerName = function(server)
	{
		if (typeof server == 'string')
		{
			if (server.indexOf('wtp.') === 0)
				server = (server.split('.'))[1];
			this._serverName = server;
		}
		else
			this._serverName = server.serverName;
		if (this._serverName && this._serverName != 'login' && this._serverName0 != this._serverName)
		{
			this._serverName0 = this._serverName;
			app.setStorage('serverName0', this._serverName);
		}
	}
	/**
	 * 清除缓存
	 */
	ajaxFun.prototype.clearCache = function(k, mustAll)
	{
		if (k && this._cache[k])
			delete this._cache[k];
		else
		{
			for ( var k in this._cache)
			{
				if (!this._cache[k])
					delete this._cache[k];
			}
			// 清除所有过期的缓存
			var tm = getTime();
			for ( var k in this._cache)
			{
				if (!this._cache[k])
				{
					delete this._cache[k];
					continue;
				}
				if (mustAll || this._cache[k].time < tm - this._cacheTime)
					delete this._cache[k];
			}
		}
	}
	/**
	 * 取得当前微服务名称
	 */
	ajaxFun.prototype.getServerName = function(isdefault, tryTestServerName)
	{
		if (tryTestServerName)
		{
			for ( var k in app.servers)
			{
				if (k == 'login')
					continue;
				if (tryTestServerName == k)
				{
					this._serverName0 = k;
					return k;
				}
			}
		}
		if (isdefault)
		{
			var s = this._serverName0;
			this._serverName0 = '';
			if (!s)
				s = app.getStorage('serverName0');
			var find = false;
			for ( var k in app.servers)
			{
				if (k == 'login')
					continue;
				if (s == k)
				{
					find = true;
					this._serverName0 = k;
					break;
				}
			}
			if (!find)
			{
				for ( var k in app.servers)
				{
					if (k == 'login')
						continue;
					this._serverName0 = k;
					break;
				}
			}
			if (!this._serverName0)
				this._serverName0 = 'login';
			this.setServerName(this._serverName0);
			var re = this._serverName0;
		}
		else
			var re = this._serverName;
		return re ? re : 'login';
	}
	/**
	 * 授权页面
	 */
	ajaxFun.prototype.setGrantAuth = function(grantAuthId, set, sure)
	{
		var that = this;
		left.setMainContentHtml();
		if (!grantAuthId)
			grantAuthId = app.getHrefPara('grantAuthId', true);
		if (!grantAuthId)
			return errorMsg(app.w('login.msg.noGrantAuthId'));
		if (set)
		{
			if (!sure)
			{
				confirm(app.w('login.msg.areYouSureSetGrantAuth'), function()
				{
					that.setGrantAuth(grantAuthId, true, true);
				}, function()
				{
					login.logOut();
				});
				return;
			}
			this.request('wtp.login.tools.grant.setGrantAuth', {
				grantAuthId : grantAuthId,
				set : 'yes',
			}, function(d, ad)
			{
				showMsg('', app.w('optionOk'), 0, function()
				{
					login.logOut();
				});
			}, function(msg, msg2, code)
			{
				if (that.getErrorCode('ER_CODE_RESOURCE_OR_ID_NOT_EXIST') == code)
				{
					confirm(app.w('login.msg.notfindGrantAuth'), function()
					{
						login.logOut();
					}, function()
					{
						login.logOut();
					});
				}
				else
				{
					confirm(msg, function()
					{
						login.logOut();
					}, function()
					{
						login.logOut();
					});
				}
			});
		}
		else
		{
			this.request('wtp.login.tools.grant.setGrantAuth', {
				grantAuthId : grantAuthId,
				set : 'no',
			}, function(d, ad)
			{
				if (d.length <= 0)
					return errorMsg(app.w('login.msg.noGrantAuthIdOrTimeout'));
				if ($('#_grantAuthId' + grantAuthId).length > 0)
					return;
				var t = '';
				t += '<p>user : ' + formatData(d[0]['userId'], 'username');
				t += '<p>business : ' + formatData(d[0]['businessId'], 'businessname');
				t += d[0]['memo'];
				t += that._getAuthStrFromnAuths(d[0]['grantAuthName']);
				t += '<p class="hidden" id="_grantAuthId' + grantAuthId + '">id : ' + grantAuthId + '</p>';
				t += '<p>' + app.w('login.msg.areYouSureSetGrantAuth') + '?';
				var okClose = false;
				confirm(t, function()
				{
					that.setGrantAuth(grantAuthId, true, sure);
					okClose = true;
				}, function()
				{
					login.logOut();
					okClose = true;
				}, false, true, function()
				{
					return okClose;
				});
			}, function(msg, msg2, code)
			{
				if (that.getErrorCode('ER_CODE_RESOURCE_OR_ID_NOT_EXIST') == code)
				{
					confirm(app.w('login.msg.notfindGrantAuth'), function()
					{
						login.logOut();
					}, function()
					{
						login.logOut();
					});
				}
				else
				{
					confirm(msg, function()
					{
						login.logOut();
					}, function()
					{
						login.logOut();
					});
				}
			});
		}
	}
	/*
	 * 取得错误代码
	 */
	ajaxFun.prototype.getErrorCode = function(ername)
	{
		var list = {
			NOT_SCAN_ALL : -4,
			NO_ORDER_OPTION : -3,
			NOT_CHANGE : -2,
			NORMAL_INFO : -1,
			ER_BAD_REQUEST : 400000,
			ER_OUTER_ID_USED : 400001,
			ER_NOT_FIND_PRODUCT : 400002,
			ER_NOT_FIND_ORDER : 400003,
			ER_NOT_EXIST_APIAPPID : 400004,
			ER_LOW_STOCKS : 400005,
			ER_SIGNATURE_ERROR : 400006,
			ER_ILLEGAL_ID : 400007,
			ER_PARAMETER_ERROR_OR_LOSS : 400008,
			ER_ORDER_STATUS_NOT_ALLOWED : 400009,
			ER_NEED_SURE : 400010,
			ER_CODE_RESOURCE_OR_ID_NOT_EXIST : 400012,
			ER_CODE_RESOURCE_OR_ID_REPEAT : 400013,
			ER_CONFIG_ERROR : 400014,
			ER_FILE_IO_ERROR : 400015,
			ER_LIMITED_FUNDS : 400016,
			ER_LOW_NUMBER : 400017,
			ER_LOGIN_BY_OTHER : 400018,
			ER_FUNCTION_NOT_OPEN : 400099,
			ER_UNAUTHORIZED : 401000,
			ER_NOT_LOGIN : 401001,
			ER_FORBIDDEN : 403000,
			ER_NEED_BINDWX : 403001,
			ER_METHOD_NOT_ALLOWED : 405000,
			ER_REQUEST_TIMEOUT : 408000,
			ER_GONE : 410000,
			ER_LOCKED : 423000,
			ER_SERVER_ERROR : 500000,
			ER_NO_METHOD : 654321
		};
		ername = (ername + ' ').trim().toUpperCase();
		if (list[ername] > 0 || list[ername] < 0)
			return list[ername];
		else
		{
			var i = parseInt(ername);
			if (i > 0 || i < 0)
			{
				for ( var k in list)
				{
					if (list[k] == i)
						return k;
				}
			}
			return ername;
		}
	}
	// ////////////////////////////////////////////
	// 以下私有函数
	// ////////////////////////////////////////////
	/**
	 * 是否显示了登录界面
	 */
	ajaxFun.prototype._isShowFace = function()
	{
		if (window.left)
			return left.isShowFace();
		else
			return true;
	}
	ajaxFun.prototype._grantAuth = function(msg, md5, auth, bid, backfun, grantAuthId, bcode, method)
	{
		var qcode_timeout = 1200; // 秒
		if (this._grantAuth_layerIndex)
			return;
		backfun = backfun || function()
		{
		};
		this._grantAuth_backfun = backfun;
		var that = this;
		grantAuthId = parseInt(grantAuthId);
		if (!grantAuthId)
		{
			// 先创建授权记录号
			this.request('wtp.login.tools.grant.CreateGrantAuth', {
				memo : msg,
				md5Sign : md5,
				auth : auth,
				bid : bid,
				method : method,
			}, function(d, ad)
			{
				if (!ad['grantAuthId'])
				{
					return errorMsg('no grantAuthId');
				}
				that._grantAuth(msg, md5, auth, bid, backfun, ad['grantAuthId'], bcode, method);
			});
			return;
		}
		var url = app.getWindowHref() + '?grantAuthId=' + grantAuthId;
		if (!bcode)
		{
			loginPrint.getQRCode(url, 300, 300, function(bcode)
			{
				that._grantAuth(msg, md5, auth, bid, backfun, grantAuthId, bcode, method);
			})
			return;
		}
		if (this._grantAuth_layerIndex)
			layer.close(this._grantAuth_layerIndex);
		var boxid = getRandId();
		var starts = getTime();
		var startsstr = '00:' + Math.floor(qcode_timeout / 60) + ':00';
		var t = '<div class="user-select" style="margin:12px auto;width:320px" id="' + boxid + '" >  ' + msg;
		t += this._getAuthStrFromnAuths(auth);
		t += '<p>businessId : ' + bid + ' &nbsp;  &nbsp;  &nbsp;  &nbsp; grantAuthId : ' + grantAuthId;
		t += '<p>url : ' + url;
		t += '<p style="text-align:center"><a onclick="ajax._setGrantAuthByPassword(' + grantAuthId + ')">' + app.w('setGrantAuthByPassword') + '</a>';
		t += ' &nbsp; &nbsp; &nbsp; &nbsp;  &nbsp; <a onclick="clearInterval(ajax._grantAuth_timer);layer.close(ajax._grantAuth_layerIndex)">' + app.w('cancel') + '</a>';
		t += ' &nbsp; &nbsp; &nbsp; &nbsp;  &nbsp; <a onclick="clearInterval(ajax._grantAuth_timer);layer.close(ajax._grantAuth_layerIndex);login.refreshToken(0, true,true, ajax._grantAuth_backfun)">' + app.w('refreshTokenAndTry') + '</a>';
		t += '<p><img src="' + bcode + '"/>'
		t += '<p style="width:300px">' + app.w('login.msg.grantAuthMsg') + '<span class="tm"> ' + startsstr + '</span></div>';
		that._grantAuth_isOk = false;
		that._grantAuth_testNow = false;
		this._grantAuth_layerIndex = showFullLayer(app.w('grantAuthMsg'), t, function()
		{
			clearInterval(that._grantAuth_timer);
			that._grantAuth_layerIndex = 0;
			that._grantAuth_timer = 0;
			if (!that._grantAuth_isOk)
			{
				// 想办法后台删除授权码
				that.request('wtp.login.tools.grant.DeleteGrantAuth', {
					id : grantAuthId,
				}, null, null, false, true);
			}
		}, false, 0.2, 'abstop');
		var tt = getTime();
		// 不断执行探寻
		this._grantAuth_timer = setInterval(function()
		{
			if ($('#' + boxid).length <= 0)
			{
				clearInterval(that._grantAuth_timer);
				return;
			}
			// 倒计时
			var t = qcode_timeout + starts - getTime();
			if (t <= 0)
			{
				layer.close(that._grantAuth_layerIndex);
				return;
			}
			if (t < 60)
				t = '00:' + (t % 60 < 10 ? '0' : '') + t % 60;
			else
			{
				var m = (Math.floor(t / 60) < 10 ? '0' : '');
				t = m + Math.floor(t / 60) + ':' + (t % 60 < 10 ? '0' : '') + t % 60;
			}
			$('#' + boxid + ' span.tm').html(' 00:' + t);
			if (getTime() - tt < 5 && !that._grantAuth_testNow)
				return;
			that._grantAuth_testNow = false;
			tt = getTime();
			that.setBackRequest(true);
			that.request('wtp.login.tools.grant.getGrantAuth', {
				grantAuthId : grantAuthId,
			}, function(d, ad)
			{
				if (d.length <= 0)
				{
					// 未发现，也可能超时了
					clearInterval(that._grantAuth_timer);
					errorMsg(app.w('login.msg.notFindGrantAuthOrTimeout'), '', function()
					{
						layer.close(that._grantAuth_layerIndex);
					});
					return;
				}
				// 探寻是否成功，成功就继续执行
				if (d[0]['grantTime'] > 0)
				{
					clearInterval(that._grantAuth_timer);
					if (d[0]['md5Sign'] != md5)
					{
						errorMsg('md5Sign error', '', function()
						{
							layer.close(that._grantAuth_layerIndex);
						});
						return;
					}
					// 成功了
					that._grantAuth_isOk = true;
					layer.close(that._grantAuth_layerIndex);
					backfun(grantAuthId, md5);
				}
			}, function(msg)
			{
				clearInterval(that._grantAuth_timer);
				errorMsg(msg, '', function()
				{
					layer.close(that._grantAuth_layerIndex);
				});
			}, false, true);
		}, 1000)
	}
	/**
	 * 取得授权密码
	 */
	ajaxFun.prototype._setGrantAuthByPassword = function(grantAuthId)
	{
		var that = this;
		var layerIndex = 0;
		var form = new formFun({
			showmemo : false,
			method : '',
			submitOtherBtn : {
				k : {
					caption : app.w('cancel'),
					fun : function()
					{
						layer.close(layerIndex);
					},
				}
			},
			preDealDataFun : function(data)
			{
				if (!login.isLogin())
				{
					errorMsg(app.w('login.msg.curUserHaveLogout'), '', function()
					{
						layer.close(layerIndex);
					});
					return;
				}
				if (data['userName'] == app.getUserName())
				{
					errorMsg(app.w('login.msg.couldNotYourself'));
					return null;
				}
				that.request('wtp.login.tools.grant.setGrantAuth', {
					grantAuthId : grantAuthId,
					set : 'yes',
					userName : data['userName'],
					passWord : md5(data['passWord']).toUpperCase(),
				}, function(d, ad)
				{
					app.setStorage('grantAuthUserName', data['userName']);
					that._grantAuth_testNow = true;
					layer.close(layerIndex);
				});
				return null;
			},
			paras : {
				userName : {
					caption : app.w('userName'),
					required : true,
					value : app.getStorage('grantAuthUserName'),
				},
				passWord : {
					inputtype : 'password',
					caption : app.w('Password'),
					required : true
				}
			}
		});
		layerIndex = showForm(app.w('userLogin'), form, null, Math.min($(window).width() * 0.9, 600), 250, null, 'abstop');
	}
	/**
	 * 显示结果信息
	 */
	ajaxFun.prototype._showMsg = function(postData, response, debug, debugMessage)
	{
		var that = this;
		if (debug && this.getErrorCode(response.code) === 'ER_SERVER_ERROR' && !debugMessage)
		{
			this.request('wtp.login.tools.getLastLog', {}, function(d, ad)
			{
				that._showMsg(postData, response, debug, ad.log + ' ');
			});
			return;
		}
		var msg = response.msg;
		msg = msg.replace(/\(wtp\..*?\)/g, '');
		msg = msg.replace(/<p>[\s\r\n]{0,32}\:/g, '<p>');
		msg = msg.replace(/<p>[\r\n]{0,32}<\/p>/g, ' ');
		msg = msg.replace(/<p>[\s\r\n]{0,32}<p>/g, '<p>');
		msg = msg.replace(/\:[\s\:]{0,32}\:/g, ':');
		msg = '<br>' + app.fw(msg);
		if (debug)
		{
			msg += '<p><b>=== Detail ===</b>';
			msg += '<p><b>' + this.getErrorCode(response.code) + '</b> : ' + response.msg.replace(/\(wtp\./g, '<br>(wtp.');
			if (!postData && response.adata && response.adata._para_)
			{
				postData = {
					para : response.adata._para_
				};
			}
			if (postData)
			{
				if (postData['token'])
				{
					var token = postData['token'];
					postData['token'] = token.substring(0, 6) + '****' + token.substring(token.length - 6, token.length);
				}
				if (postData['para'])
				{
					try
					{
						var j = JSON.parse(postData['para']);
						if (j)
						{
							for ( var k in j)
							{
								if (k.indexOf('password') >= 0)
									j[k] = '***';
							}
							postData['para'] = arrToShowStr(j);
						}
					}
					catch (err)
					{
					}
				}
				msg += '<p><b>=== Request Data ===</b>' + arrToShowStr(postData);
			}
			if (debugMessage)
			{
				msg += '<p><b>=== Debug Message ===</b><p>' + debugMessage;
			}
		}
		else if (postData && postData['method'])
		{
			msg = '(' + postData['method'] + ')' + msg;
		}
		if (this.getErrorCode(response.code) === 'ER_SERVER_ERROR')
		{
			msg += '<p>&nbsp;<p><a onclick="ajax.sendLastLog();">' + app.w('login.msg.sendDebugMessageToMe') + '</a></p>'
		}
		this._showMsg.layerIndex = showMsg(app.w('info'), msg, 0, null, response.code <= 0 ? 6 : 2, app.w('close'), false, false, {
			title : debug ? app.w('simple') : app.w('detail'),
			fun : function()
			{
				that._showMsg(postData, response, !debug);
			}
		}, 'scroll');
	}
	ajaxFun.prototype.sendLastLog = function(method, thisUrl)
	{
		layer.close(ajax._showMsg.layerIndex);
		var that = this;
		setTimeout(function()
		{
			that.request('wtp.login.tools.getLastLog', {
				'justSendWorkSheet' : 'yes'
			}, function(d, ad)
			{
				layer.msg(app.w('optionOK'));
			});
		}, 500);
	}
	/**
	 * 根据method取得访问网址
	 */
	ajaxFun.prototype.getUrl = function(method, thisUrl)
	{
		if (method && method.indexOf('wtp.') === 0)
		{
			var a = method.split('.');
			if (a.length >= 2)
			{
				return thisUrl || app.getServerUrl(a[1]);
			}
		}
		return '';
	}
	/**
	 * 根据请求结果得出是否需要授权
	 */
	ajaxFun.prototype._haveNeedAuths = function(response)
	{
		if (response && response.adata && response.adata['needAuths'] && response.adata['needAuthsBusinessId'])
		{
			var a = response.adata['needAuths'].split(',');
			return a.length > 0;
		}
		return false;
	}
	/**
	 * 根据权限取得相应的权限字符串
	 */
	ajaxFun.prototype._getAuthStrFromnAuths = function(auths)
	{
		if (!auths)
			return '';
		var a = auths.split(',');
		msg = '';
		for (var i = 0; i < a.length; i++)
		{
			var ai = a[i].trim().split('.');
			if (ai.length >= 2)
			{
				var s = ai[0];
				var sa = ai[1];
				for (var j = 0; j < sa.length; j++)
				{
					var sai = sa.substring(j, j + 1);
					msg += '<p class="red">' + s + '.' + sai + ' : ' + configPara.val('auth', s, sai);
				}
			}
		}
		return msg;
	}
	ajaxFun.prototype.loading = function(timeout)
	{
		if (!timeout)
			this._waiting(-1);
		else
			this._waiting(0, 0, timeout, true);
	}
	/**
	 * 弹出等待框
	 */
	ajaxFun.prototype._waiting = function(afterms, runStartTime, timeout, justQuan, method)
	{
		if (arguments.length == 0)
			return !!this._waiting_in;
		var that = this;
		if (afterms < 0)
		{
			// 关闭即将弹出的东西
			if (this._waiting_timer)
			{
				clearTimeout(this._waiting_timer);
				this._waiting_timer = null;
				this._waiting_in = false;
			}
			this._waiting_in = false;
			if (this._waiting_interval)
			{
				// 清除时钟
				clearInterval(this._waiting_interval);
				this._waiting_interval = 0;
			}
			// 关闭进度条，关闭旋转
			this._setTopRunningStatus(false);
			if (this._waiting_cindex)
			{
				layer.close(this._waiting_cindex);
				this._waiting_cindex = 0;
			}
			return;
		}
		else if (afterms > 0)
		{
			// 打开旋转
			this._setTopRunningStatus(true);
			// 关闭即将弹出的东西
			if (this._waiting_timer)
			{
				clearTimeout(this._waiting_timer);
				this._waiting_timer = null;
				this._waiting_in = false;
				afterms = 1;
			}
			this._waiting_timer = setTimeout(function()
			{
				that._waiting(0, runStartTime, timeout, false, method);
			}, afterms);
			return;
		}
		if (!justQuan)
			this._waiting_in = true;
		// 关闭正在进行的
		if (this._waiting_cindex)
		{
			layer.close(this._waiting_cindex);
			this._waiting_cindex = 0;
		}
		if (!window.left || !left.showWrapper())
		{
			// 在欢迎页面，不显示进度条
			return;
		}
		// 进度条（超时时间大于标准来时间）
		var d2 = timeout; // 总耗时
		if (d2 > config.ajaxTimeout && !justQuan)
		{
			var d1 = new Date().getTime() - runStartTime; // 已经耗时
			var d21 = d2 / 1000;
			var al = 100 + (d21 - 30); // 进度条长度
			if (al > 200)
				al = 200;
			this._waiting_cindex = layer.msg(that._getGrogressBar(d1, d2, al), {
				time : d2,
				shade : 0.1,
				end : function()
				{
					that._waiting_cindex = 0;
					that._waiting_in = false;
				}
			});
			this._waiting_interval = setInterval(function()
			{
				if (that._waiting_cindex)
				{
					var d1 = new Date().getTime() - runStartTime;
					var kk = $('#layui-layer' + that._waiting_cindex + ' .layui-layer-content');
					if (kk.length <= 0)
					{
						clearInterval(that._waiting_interval);
						that._waiting_interval = 0;
						layer.close(this._waiting_cindex);
						that._waiting_cindex = 0;
						that._waiting_in = false;
					}
					else
					{
						kk.html(that._getGrogressBar(d1, d2, al));
					}
				}
				else if (that._waiting_interval)
				{
					// 如果进度条已经不存在，则清除时钟
					clearInterval(that._waiting_interval);
					that._waiting_interval = 0;
					that._waiting_in = false;
				}
			}, 333);
		}
		else
		{
			if (config.debug && method)
			{
				console.log('==' + method + '==');
				var t = new Date().getTime();
			}
			this._waiting_cindex = layer.open({
				type : 3,
				icon : 1,
				shade : 0.05,
				time : timeout,
				end : function()
				{
					that._waiting_cindex = 0;
					that._waiting_in = false;
					if (config.debug && method)
					{
						t = new Date().getTime() - t;
						console.log(t + 'ms');
					}
				}
			});
		}
	}
	/**
	 * 设置进度条的状态
	 */
	ajaxFun.prototype._setTopRunningStatus = function(isrun, failed, failedmsg)
	{
		var nf = $('.refreshpage');
		if (isrun)
		{
			nf.addClass('rotation');
			nf.removeClass('fa-warning');
		}
		else
		{
			nf.removeClass('rotation');
			if (failed)
			{
				nf.addClass('fa-warning');
				if (!failedmsg)
					failedmsg = 'request failed';
				nf.attr('title', failedmsg);
				layer.tips(failedmsg, nf);
			}
			if (!nf.hasClass('fa-warning'))
				nf.attr('title', app.w('refresh'));
		}
	}
	/**
	 * 向url后添加参数
	 */
	ajaxFun.prototype._addToUrl = function(url, paraStr)
	{
		if (url.indexOf('?') == url.length - 1 || url.indexOf('&') == url.length - 1)
		{
			return url + paraStr;
		}
		else if (url.indexOf('?') > 0)
		{
			return url + "&" + paraStr;
		}
		else
			return url + '?' + paraStr;
	}
	/**
	 * 取得进度条
	 */
	ajaxFun.prototype._getGrogressBar = function(d1, d2, al)
	{
		var t1 = Math.round(d1 / 1000) + 's';
		var t2 = Math.round(d2 / 1000) + 's';
		if (d2 <= 0 || !d2)
			d2 = 100;
		if (d1 <= 0 || !d1)
			d1 = 0;
		var d = al * d1 / d2;
		var h = '';
		if (this.runCaption)
		{
			h += '<p style="text-align:left;display:' + (this._showGrogressBarCaption() || this.runCaption.indexOf('wtp.') !== 0 ? 'block' : 'none') + '" class="_waiting_grogressbar">' + this.runCaption + '</p>';
		}
		h += '<div class="grogressbar" style="width:' + al + 'px;"><div class="line" style="width:' + d + 'px">';
		if (d1 / d2 < 0.5)
			h += '</div><div class="text">&nbsp;' + t1 + '</div></div>';
		else
			h += '' + t1 + '&nbsp;</div></div>';
		h += ' ' + t2;
		h += ' &nbsp; <a title="' + app.w('backRun') + '" onclick="ajax._waiting(-1)"><i class="fa fa-chevron-circle-down white"></i></a>';
		h += ' &nbsp; <a title="' + app.w('backRun') + '" onclick="ajax._showGrogressBarCaption(null)"><i class="fa' + (this._showGrogressBarCaption() ? ' fa-caret-down' : ' fa-caret-up') + ' white"></i></a>';
		return h;
	}
	/**
	 * 显示进度条标题
	 */
	ajaxFun.prototype._showGrogressBarCaption = function(show)
	{
		if (arguments.length == 0)
			return this._waiting_showCaption;
		if (show === true || show === false)
			this._waiting_showCaption = show;
		else
			this._waiting_showCaption = !this._waiting_showCaption;
		if (this._waiting_showCaption)
			$('._waiting_grogressbar').show();
		else
			$('._waiting_grogressbar').hide();
	}
	window.ajax = new ajaxFun();
}());
